package cn.yangliu.init;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * The type of package-scan.
 *
 * <p>
 * .
 *
 * @author 问道于盲
 * @date 2020 -04-16
 */
public class Scanner {

    private static final String RESOURCE_PATTERN = "/**/*.class";

    /**
     * Scan list.
     *
     * @param packages the packages
     * @return the list
     */
    public static List<Class<?>> scan(String ... packages){
        List<Class<?>> classes = new ArrayList<>();
        for (String aPackage : packages) {
            classes.addAll(loadClass(aPackage));
        }
        return classes;
    }


    /**
     * 包扫描
     *
     * @param basePackage
     * @return
     */
    private static Set<Class<?>> loadClass(String basePackage)  {
        try{
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

            String pattern  = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(basePackage) +
                    RESOURCE_PATTERN;
            Resource[] resources = resolver.getResources(pattern);

            MetadataReaderFactory factory = new CachingMetadataReaderFactory(resolver);
            Set<Class<?>> classes = new HashSet<>();
            for (Resource resource : resources) {
                if (!resource.isReadable()) {
                    continue;
                }
                loadClass(resource, factory, classes);
            }
            return classes;
        }catch (Exception e) {
            throw new UnsupportedOperationException(e);
        }
    }

    private static void loadClass(Resource resource, MetadataReaderFactory factory, Set<Class<?>> classes) {
        MetadataReader metadataReader = null;
        try {
            metadataReader = factory.getMetadataReader(resource);
            String className = metadataReader.getClassMetadata().getClassName();
            Class<?> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
            classes.add(clazz);
        } catch (Throwable e) {

        }
    }
}
